home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacGofer 0.22d / MacGofer Sources / mac_project.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-09  |  27.6 KB  |  1,430 lines  |  [TEXT/MPS ]

  1. /*****************************************************************************
  2.  
  3.   mac_project.c:  Copyright (c) Kevin Hammond 1993.   All rights reserved.
  4.   
  5.   This module implements the Macintosh graphical project handling.
  6.  
  7. *****************************************************************************/
  8.  
  9.  
  10. #include "mac.h"
  11. #include <fcntl.h>
  12. #include "ctype.h"
  13.  
  14. #pragma segment Project
  15.  
  16. extern CursHandle watchcurs;                /* Watch cursor */
  17. extern short      systemVersion;        /* Which version of the system we're running */
  18.  
  19. static projfiles = 1;
  20.  
  21. char  projfile[256];
  22. short projvol = 0;
  23. long  projdirID = 0;
  24. short projrespath = -1;
  25.  
  26. short preludevolref = 0;
  27. long  preludedirID = 0;
  28. char  *PreludeName = "";
  29.  
  30. extern char *askgetfile(), *getfile(), *putfile(), *readFilename();
  31.  
  32. extern Boolean doreadproject();
  33.  
  34. ListHandle SetUpDefnList(), createlist();
  35.  
  36. short GetModFromIndex();
  37.  
  38. extern ListHandle SetUpModuleList();
  39. extern short KeyModifiers;
  40.  
  41. extern pascal  Boolean ListDlgFilter();
  42. extern short   dlgOtherButton;
  43.  
  44.  
  45. #define MAX_PITEMS 40
  46.  
  47. struct ProjStruct
  48.   {
  49.     Boolean PUsed;
  50.     short pvrefnum;
  51.     long pdirID;
  52.     char *FName;
  53.     char *MName;
  54.     unsigned long ModTime;
  55.   }
  56. ProjItems[MAX_PITEMS] = {FALSE,0,0L,NIL,NIL,0L};
  57.  
  58.  
  59. #define PUSED(i)     (ProjItems[i].PUsed)
  60. #define PVREFNUM(i)    (ProjItems[i].pvrefnum)
  61. #define PDIRID(i)    (ProjItems[i].pdirID)
  62. #define PNAME(i)    (ProjItems[i].FName)
  63. #define MNAME(i)    (ProjItems[i].MName)
  64. #define PMODTIME(i)    (ProjItems[i].ModTime)
  65.  
  66. char *safemalloc();
  67.  
  68. unsigned long getmodtime();
  69.  
  70.  
  71. NewPItem(name,refnum,dirID)
  72. char *name;
  73. short refnum;
  74. long dirID;
  75. {
  76.   AddPItem(name,refnum,dirID,FALSE);
  77. }
  78.  
  79.  
  80. int AddPItem(name,refnum,dirID,preservemodtime)
  81. char *name;
  82. short refnum;
  83. long dirID;
  84. int preservemodtime;
  85. {
  86.   int i, used;
  87.   int theversion;
  88.   char *namebuf;
  89.   
  90.   i = FindAnyPItem(name,refnum,dirID,&used);
  91.   
  92.   if(used)
  93.     return(TRUE);
  94.   
  95.   theversion = resetpversions(name,FALSE);
  96.  
  97.   if( i < 0 )
  98.     {
  99.        preservemodtime = FALSE;
  100.        for(i=0; i < MAX_PITEMS; ++i)
  101.          if(PUSED(i)!=TRUE)
  102.             break;
  103.  
  104.        if(i == MAX_PITEMS)
  105.          return(FALSE);
  106.     }
  107.  
  108.   namebuf = safemalloc(strlen(name)+1);
  109.   strcpy(namebuf,name);
  110.  
  111.   resolvealias(&namebuf,&refnum,&dirID);
  112.  
  113.   PUSED(i) = TRUE;
  114.   if(!preservemodtime)
  115.     {
  116.        /* Change names */
  117.        if(PNAME(i)!=NIL)
  118.          free(PNAME(i));
  119.        if(MNAME(i)!=NIL && MNAME(i)!=PNAME(i))
  120.          free(PNAME(i));
  121.        PNAME(i) = MNAME(i) = namebuf;
  122.        PVREFNUM(i) = refnum;
  123.        PDIRID(i) = dirID;
  124.        PMODTIME(i) = 0;
  125.      }
  126.    setmname(theversion,i);
  127.    insmenuitem(Menu_Project,MNAME(i),PreludeItem+projfiles++);
  128.    return(preservemodtime);
  129. }
  130.  
  131.  
  132. setmname(version,i)
  133. int version, i;
  134. {
  135.   if(MNAME(i)!=PNAME(i) && MNAME(i) != NIL)
  136.     free(MNAME(i));
  137.  
  138.   MNAME(i) = PNAME(i);
  139.   if(version > 0)
  140.     {
  141.       MNAME(i) = safemalloc(strlen(PNAME(i))+4);
  142.       sprintf(MNAME(i),"%s:%d",PNAME(i),version);
  143.     }
  144. }
  145.  
  146.  
  147. char ftolower(c)
  148. char c;
  149. {
  150.   if(isupper(c))
  151.     return(tolower(c));
  152.   else
  153.     return(c);
  154. }
  155.  
  156.  
  157. Boolean equalfiles(f1,f2)
  158. char *f1, *f2;
  159. {
  160.   /* Just in case a window has a null filename -- HSL */
  161.   if (f1 == NIL || f2 == NIL)
  162.     return(FALSE);
  163.  
  164.   for(; *f1 != '\0'; f1++, f2++)
  165.     if(ftolower(*f1) != ftolower(*f2))
  166.       return(FALSE);
  167.   return(*f2=='\0');
  168. }
  169.  
  170.  
  171. int resetpversions(name,deleting)
  172. char *name;
  173. Boolean deleting;
  174. {
  175.   int version = 0, i;
  176.   
  177.   if(deleting)
  178.     {
  179.       int count = 0, pindex;
  180.       for(i=0; i < MAX_PITEMS; ++i)
  181.         if(PUSED(i) && equalfiles(name,PNAME(i)))
  182.       {
  183.         ++count;
  184.         pindex = i;
  185.       }
  186.       
  187.       if (count == 1)
  188.         {
  189.           short menuitem = findmenuitem(Menu_Project,PreludeItem,projfiles+PreludeItem+1,MNAME(pindex));
  190.       setmname(0,pindex);
  191.       setitem(Menu_Project,menuitem,MNAME(pindex));
  192.       return(0);
  193.     }
  194.     }
  195.  
  196.   for(i=0; i < MAX_PITEMS; ++i)
  197.     if(PUSED(i) && equalfiles(name,PNAME(i)))
  198.       {
  199.         short menuitem = findmenuitem(Menu_Project,PreludeItem,projfiles+PreludeItem+1,MNAME(i));
  200.     setmname(++version,i);
  201.     setitem(Menu_Project,menuitem,MNAME(i));
  202.       }
  203.  
  204.   return(version==0?0:version+1);
  205. }
  206.  
  207.  
  208.  
  209. InitPItems()
  210. {
  211.   int i;
  212.   
  213.   for(i=0; i < MAX_PITEMS; ++i)
  214.     {
  215.       PUSED(i) = FALSE;
  216.       PVREFNUM(i) = 0;
  217.       PDIRID(i) = 0;
  218.       PMODTIME(i) = 0;
  219.       PNAME(i) = MNAME(i) = NIL;
  220.     }
  221. }
  222.  
  223.  
  224. /*
  225.     I've tried to speed this up, by removing some
  226.     resolvealias calls, and by limiting the search
  227.     to projitems live entries.
  228. */
  229.  
  230. int FindPItem(oname,refnum,dirID)
  231. char *oname;
  232. short refnum;
  233. long dirID;
  234. {
  235.   int used, i;
  236.   i = FindAnyPItem(oname,refnum,dirID,&used);
  237.   if(!used)
  238.     return(-1);
  239.   else
  240.     return(i);
  241. }
  242.  
  243. int FindAnyPItem(oname,refnum,dirID,used)
  244. char *oname;
  245. short refnum;
  246. long dirID;
  247. int *used;
  248. {
  249.   int i;
  250.   char *name = oname, *pname;
  251.   short prefnum;
  252.   long pdirID;
  253.   int founditems = 0;
  254.   
  255.   resolvealias(&name,&refnum,&dirID,TRUE);
  256.  
  257.   for(i=0; i < MAX_PITEMS; ++i)
  258.     if(PNAME(i) != NIL)
  259.       {
  260.         *used = PUSED(i);
  261.         pname =   PNAME(i);
  262.     prefnum = PVREFNUM(i);
  263.     pdirID =  PDIRID(i);
  264. //        resolvealias(&pname,&prefnum,&pdirID,FALSE);
  265.         if(equalfiles(pname,name) && prefnum==refnum && pdirID==dirID)
  266.           {
  267.         if(name != oname)
  268.           free(name);
  269.         return(i);
  270.       }
  271.     else if (++founditems == projfiles)
  272.       break;
  273.       }
  274.  
  275.   if(name != oname)
  276.     free(name);
  277.  
  278.   *used = FALSE;
  279.   return(-1);
  280. }
  281.  
  282.  
  283. int FindPMItem(name)
  284. char *name;
  285. {
  286.   int i;
  287.  
  288.   for(i=0; i < MAX_PITEMS; ++i)
  289.     if(PUSED(i) && equalfiles(MNAME(i),name))
  290.       return(i);
  291.  
  292.   return(-1);
  293. }
  294.  
  295.  
  296.  
  297. DelPItem(pindex)
  298. int pindex;
  299. {  
  300.   if(pindex >= 0)
  301.     {
  302.       PUSED(pindex) = FALSE;
  303.  
  304. #if 0
  305.       if(PNAME(pindex)!=NIL)
  306.         free(PNAME(pindex));
  307.       if(MNAME(pindex)!=NIL && MNAME(pindex)!=PNAME(pindex))
  308.         free(PNAME(pindex));
  309.       PNAME(pindex) = MNAME(pindex) = NIL;
  310.  
  311.       PMODTIME(pindex) = 0;
  312.       PVREFNUM(pindex) = 0;
  313.       PDIRID(pindex) = 0;
  314. #endif
  315.     }
  316. }
  317.  
  318.  
  319. /*
  320.     Clear the project menu.
  321. */
  322.  
  323. clearProject()
  324. {
  325.   int max = CountMItems(Menu_Project);
  326.   int i;
  327.   
  328.   /* Record the old Prelude modification time */  
  329.   unsigned long modtime = PMODTIME(0);
  330.   
  331.   while (max >= PreludeItem)
  332.     DelMenuItem(Menu_Project,max--);
  333.  
  334.   for(i=0; i < MAX_PITEMS; ++i)
  335.     DelPItem(i);
  336.  
  337.   projfiles = 0;
  338.   
  339.   if(*PreludeName != '\0')
  340.       AddPItem(PreludeName,preludevolref,preludedirID,TRUE);
  341.     
  342.   forgetprojresources();
  343.     
  344.   forgetScriptsFrom(1);
  345.   /* So the user is prompted if the project is saved */
  346.   projfile[0] = '\0';
  347. }
  348.  
  349.  
  350.  
  351. /* Forget the old project resources */
  352. forgetprojresources()
  353. {
  354.   if(projrespath >= 0)
  355.     {
  356.       CloseResFile(projrespath);
  357.       projrespath = -1;
  358.     }
  359. }
  360.  
  361.  
  362. /* Use the project resources/standard Gofer resources */
  363. useprojectresfile(useprojfile,forget)
  364. int useprojfile, forget;
  365. {
  366.   extern short goferresfile;
  367.   
  368.   if(useprojfile)
  369.     if(projrespath >= 0)
  370.       UseResFile(projrespath);
  371.     else
  372.       setprojresfile(projfile,projvol,projdirID);
  373.  
  374.   else
  375.     {
  376.       /* Forget the Project resources */
  377.       if(forget)
  378.         forgetprojresources();
  379.  
  380.       /* And get the Application resources */
  381.       UseResFile(goferresfile);
  382.     }
  383. }
  384.  
  385. openProject()
  386. {
  387.   char *nprjfile = askgetfile(1,projtypelist,"Open Gofer Project","Open",0,Res_Dlg_SFP_Project);
  388.   if(*nprjfile != '\0')
  389.     (void) doreadproject(nprjfile,ReplySpec.vRefNum,ReplySpec.parID);
  390. }
  391.  
  392.  
  393.  
  394. /*
  395.     "Text" version of openProject.
  396. */
  397.  
  398. project()
  399. {
  400.   long    parID = *((long *)CurDirStore);
  401.   short vRefNum = -1 * (*(short *)SFSaveDisk);
  402.   char *prjfile = readFilename();
  403.  
  404.   /* If we have a legal project file, read it */
  405.   /* We should check that the file has the correct type somewhere */
  406.   if(prjfile != NIL && *prjfile != '\0')
  407.     {
  408.       resolvealias(&prjfile,&vRefNum,&parID,FALSE);
  409.       (void) doreadproject(prjfile,vRefNum,parID);
  410.      }
  411.  
  412.    else
  413.      {
  414.        mprintf("ERROR: A project file name must be given\n");
  415.        printPrompt();
  416.      }
  417. }
  418.  
  419.  
  420. setprojresfile(file,volnum,dirID)
  421. char *file;
  422. short volnum;
  423. long dirID;
  424. {
  425.    extern short goferresfile;
  426.  
  427.    /* Find the project's resource map */
  428.    projrespath =  HOpenResFile(volnum,dirID,c2pstr(file),fsRdPerm);
  429.    (void) p2cstr(file);
  430. }
  431.  
  432. char *saveprojdialog(defaultsave)
  433. char *defaultsave;
  434. {
  435.   return(putfile("Save Current Project as:",
  436.                  *defaultsave == '\0'? "Untitled Project": defaultsave,
  437.          "Save"));
  438. }
  439.  
  440.  
  441. saveProject()
  442. {
  443.   dosaveproject(*projfile == '\0');
  444. }
  445.  
  446.  
  447. saveProjectAs()
  448. {
  449.   dosaveproject(TRUE);
  450. }
  451.  
  452.       
  453. dosaveproject(dodialog)
  454. Boolean dodialog;
  455. {
  456.   char savefile[256];
  457.   short saveref;
  458.   static short volnum;
  459.   static long dirID;
  460.  
  461.   if(dodialog)
  462.     {
  463.       strcpy(savefile,saveprojdialog(projfile));
  464.       if (*savefile == '\0')
  465.         return;
  466.       volnum = ReplySpec.vRefNum;
  467.       dirID = ReplySpec.parID;
  468.       updatewindows();
  469.     }
  470.   else
  471.     {
  472.       strcpy(savefile,projfile);
  473.       volnum = projvol;
  474.       dirID = projdirID;
  475.     }
  476.   
  477.   createfile(savefile,volnum,dirID,projtype);
  478.   setfiletype(savefile,volnum,dirID,creator,projtype);
  479.   
  480.   if (hopen(savefile,volnum,dirID,fsWrPerm,&saveref) != noErr)
  481.     Error("I/O ","Can't Write Project File");
  482.  
  483.   else
  484.     {
  485.       char itemfile[256];
  486.       Boolean write_error = FALSE;
  487.       short i;
  488.       long count = 0;
  489.  
  490.       /* (Re)-set the EOF marker.  Humayan forgot to do this in the new code. */     
  491.       for(i=PreludeItem+1;i<PreludeItem+projfiles;++i)
  492.         {
  493.        GetItem(Menu_Project,i,(Str255) itemfile);
  494.        count += itemfile[0] + 1;
  495.      }
  496.   
  497.       if(SetEOF(saveref,count) != noErr)
  498.          {
  499.         Error("I/O ","Write of Project File Failed");
  500.         write_error = TRUE;
  501.      }
  502.      
  503.  
  504.       /*
  505.      Should check vRefNum and write a full or relative path name
  506.       */       
  507.  
  508.       for(i=PreludeItem+1;i<PreludeItem+projfiles && !write_error;++i)
  509.         {
  510.        GetItem(Menu_Project,i,(Str255) itemfile);
  511.   
  512.        count = itemfile[0] + 1;
  513.        if (FSWrite (saveref,&count,(Ptr)itemfile) != noErr)
  514.              {
  515.             Error("I/O ","Write of Project File Failed");
  516.             write_error = TRUE;
  517.          }
  518.     }
  519.       (void) FSClose(saveref);
  520.  
  521.  
  522.       if(!write_error)
  523.         {
  524.           strcpy(projfile,savefile);
  525.       projvol = volnum;
  526.           projdirID = dirID;
  527.     }
  528.     }
  529. }
  530.  
  531.  
  532. /*
  533.     Filter out files which are already in the project,
  534.     or which are invisible.
  535. */
  536.  
  537. pascal Boolean projectFileFilter(CInfoPBPtr pb)
  538. {
  539.   if (pb->hFileInfo.ioFlFndrInfo.fdFlags & fInvisible)
  540.     return(TRUE);
  541.  
  542.   else
  543.     {
  544.       char name[256];
  545.       short vrefnum = pb->hFileInfo.ioVRefNum;
  546.       long dirID =  pb->hFileInfo.ioFlParID;
  547.   
  548.       pstrcopy(pb->hFileInfo.ioNamePtr,name);
  549.       p2cstr(name);
  550.  
  551.       return( FindPItem(name,vrefnum,dirID) != -1 );
  552.    }
  553. }
  554.  
  555.  
  556. loadProjectFile()
  557. {
  558.   Point    where;
  559.   extern SFReply sfgTheReply;
  560.   extern pascal short myDlgHook();
  561.   extern pascal Boolean myFilterProc();
  562.   extern pascal void sfgCleanup();
  563.   
  564.   SetPt(&where,-1,-1);
  565.   
  566.   sfpgetfile(&where,"\Load files into project:",(FileFilterProcPtr)projectFileFilter,1,(SFTypeList)texttypelist,myDlgHook,&sfgTheReply,Res_Dlg_Load_Multiple,myFilterProc);
  567.  
  568.   if (sfgTheReply.good)
  569.     {
  570.       sfgProcessData(NewPItem);
  571.       windowtofront(worksheet);
  572.       updatewindows();
  573.       reloadProjectFiles();
  574.     }
  575.   sfgCleanup();
  576. }
  577.  
  578.  
  579. /*
  580.     "Text" version of load, which adds to the Project menu correctly.
  581. */
  582.  
  583.  
  584. load()
  585. {
  586.   if(doload())
  587.     {
  588.       windowtofront(worksheet);
  589.       updatewindows();
  590.       reloadProjectFiles();
  591.     }
  592. }
  593.  
  594.  
  595. /* Do the load -- separated because we want to declare shorts here */
  596.  
  597. doload()
  598. {
  599.   long    parID = *((long *)CurDirStore);
  600.   short vRefNum = -1 * (*(short *)SFSaveDisk);
  601.   char *s;
  602.  
  603.   while (s=readFilename())
  604.     {
  605.       /* If the file exists add it to the project */
  606.       if(checkFileExists(s,vRefNum,parID))
  607.         AddPItem(s,vRefNum,parID,FALSE);
  608.  
  609.       /* otherwise, flag an error */
  610.       else
  611.         {
  612.           mprintf("ERROR: couldn't find %s, load aborted\n",s);
  613.       return(FALSE);
  614.         }
  615.     }
  616.  
  617.   /* Only if all files loaded OK do we want to reload the project */
  618.   return(TRUE);
  619. }
  620.  
  621.  
  622. reloadProjectFiles()
  623. {
  624.   windowtofront(worksheet);
  625.   SetCursor(*watchcurs);
  626.   readScripts(0);
  627.   printPrompt();
  628. }
  629.  
  630.  
  631. unloadprojlist(list)
  632. ListHandle list;
  633. {
  634.   Cell sel;
  635.   short item, minitem = 32767, deleted = 0;
  636.   int pindex;
  637.   char mtitle[256];
  638.   
  639.   /* Remove the selected items from the internal list */
  640.   SetPt(&sel,0,0);
  641.  
  642.   while(LGetSelect(TRUE,&sel,list))
  643.     {
  644.       sel.v += 1;
  645.       item = sel.v;
  646.       if(item < minitem)
  647.         minitem = item;
  648.  
  649.       getitem(Menu_Project,item+PreludeItem,mtitle);
  650.       --projfiles;
  651.  
  652.       pindex = FindPMItem(mtitle);
  653.       PUSED(pindex) = FALSE;
  654.       resetpversions(PNAME(pindex),TRUE);
  655.       DelPItem(pindex);
  656.      }
  657.  
  658.  
  659.   /* Now remove them from the menu */
  660.   SetPt(&sel,0,0);
  661.  
  662.   while(LGetSelect(TRUE,&sel,list))
  663.     {
  664.       sel.v += 1;
  665.       item = sel.v;
  666.       getitem(Menu_Project,item+PreludeItem-deleted,mtitle);
  667.       DelMenuItem(Menu_Project,item+PreludeItem-deleted);
  668.       ++deleted;
  669.      }
  670.   resetScript(minitem);
  671. }
  672.  
  673.  
  674. unloadProjectFile()
  675. {
  676.   DialogPtr projdlg;
  677.   short itemhit;
  678.   ListHandle unloadlist;
  679.  
  680.   /* Set the arrow cursor */
  681.   SetCursor(&(qd.arrow));
  682.  
  683.   /* Initialise dialog */  
  684.   projdlg = GetNewDialog(Res_Dlg_Unload,nil,(WindowPtr) -1);
  685.   ShowWindow(projdlg);
  686.   highlightDefault(projdlg);
  687.   
  688.   dlgOtherButton = 0;
  689.  
  690.   DisableButton(projdlg,OK);
  691.  
  692.   /* Initialise list */
  693.   unloadlist = SetUpModuleList(projdlg, Res_DItem_Unload, TRUE,FALSE,1);
  694.  
  695.   HLock((Handle)unloadlist);
  696.   (*unloadlist)->selFlags = lNoExtend;
  697.  
  698.   for(;;)
  699.     {
  700.       ModalDialog((ModalFilterProcPtr) ListDlgFilter,&itemhit);
  701.       switch(itemhit)
  702.         {
  703.       case Res_DItem_Unload:
  704.         {
  705.           Point mousePt;
  706.           GrafPtr savePort;
  707.           Cell cell;
  708.           Boolean doubleclick;
  709.  
  710.           GetPort(&savePort);
  711.           SetPort((*unloadlist)->port);
  712.           GetMouse(&mousePt);
  713.           SetPort(savePort);
  714.  
  715.  
  716.           /* Check for a double-click in the unload list */
  717.           doubleclick = LClick(mousePt,KeyModifiers,unloadlist);
  718.           SetPt(&cell,0,0);
  719.               if(LGetSelect(TRUE,&cell,unloadlist))
  720.             EnableButton(projdlg,OK);
  721.           
  722.           if(!doubleclick)
  723.         break;
  724.           itemhit = OK;
  725.         }
  726.  
  727.           case OK:
  728.         {
  729.           Cell cell;
  730.  
  731.           SetPt(&cell,0,0);
  732.  
  733.           if(!LGetSelect(TRUE,&cell,unloadlist))
  734.             {
  735.               SysBeep(1);
  736.           break;
  737.                 }
  738.           HUnlock((Handle)unloadlist);
  739.           unloadprojlist(unloadlist);
  740.           LDispose(unloadlist);
  741.               DisposDialog(projdlg);
  742.           HiliteMenu(0);
  743.           reloadProjectFiles();
  744.           return;
  745.         }
  746.             
  747.           case CANCEL:
  748.         HUnlock((Handle)unloadlist);
  749.         LDispose(unloadlist);
  750.             DisposDialog(projdlg);
  751.             return;
  752.         }
  753.     }
  754. }
  755.  
  756.  
  757. /*
  758.     "Text" version of unload, which deals with the Project menu correctly.
  759. */
  760.  
  761. unload()
  762. {
  763.   int minitem;
  764.   if(dounload(&minitem))
  765.     {
  766.       resetScript(minitem);
  767.       reloadProjectFiles();
  768.     }
  769.   else
  770.    printPrompt();
  771. }
  772.  
  773.  
  774. dounload(minitem)
  775. int *minitem;
  776. {
  777.   char *s;
  778.   Boolean unloaded = FALSE;
  779.  
  780.   *minitem = 32767;
  781.  
  782.   while (s=readFilename())
  783.     {
  784.       int pindex = FindPMItem(s);
  785.       if(pindex > 0)
  786.         {
  787.            short menuitem = findmenuitem(Menu_Project,PreludeItem+1,projfiles+PreludeItem+1,MNAME(pindex));
  788.        --projfiles;
  789.            PUSED(pindex) = FALSE;
  790.            resetpversions(PNAME(pindex),TRUE);
  791.            DelPItem(pindex);
  792.        DelMenuItem(Menu_Project,menuitem);
  793.        unloaded = TRUE;
  794.        if(pindex < *minitem)
  795.          *minitem = pindex;
  796.     }
  797.       else
  798.         mfprintf(stderr,"Error: %s is not in the current project\n",s);
  799.     }
  800.  
  801.   return(unloaded);
  802. }
  803.  
  804.  
  805.  
  806. rearrangeProjectFiles()
  807. {
  808.   DialogPtr rearrangedlg;
  809.   ListHandle oldlist, newlist;
  810.   int oldfiles = projfiles-1, newfiles = 0;
  811.   Point mousePt;
  812.   GrafPtr savePort;
  813.   Cell cell;
  814.   short itemhit;
  815.   ListHandle fromlist, tolist;
  816.   
  817.   if(oldfiles == 0)
  818.     return;
  819.  
  820.   /* Set the arrow cursor */
  821.   SetCursor(&(qd.arrow));
  822.  
  823.   /* Initialise dialog */  
  824.   rearrangedlg = GetNewDialog(Res_Dlg_Rearrange,nil,(WindowPtr) -1);
  825.   ShowWindow(rearrangedlg);
  826.   highlightDefault(rearrangedlg);
  827.   
  828.   dlgOtherButton = 0;
  829.  
  830.   /* Disable buttons which cannot be used initially */
  831.   DisableButton(rearrangedlg,Res_DItem_Reload);
  832.   DisableButton(rearrangedlg,Res_DItem_Move);
  833.  
  834.   /* Initialise lists */
  835.   oldlist = SetUpModuleList(rearrangedlg,Res_DItem_OldList,TRUE,FALSE,1);
  836.   newlist = createlist(rearrangedlg,Res_DItem_NewList,0,TRUE);
  837.  
  838.   HLock((Handle)oldlist);
  839.   HLock((Handle)newlist);
  840.   (*oldlist)->selFlags = lNoExtend;
  841.   (*newlist)->selFlags = lNoExtend;
  842.  
  843.   LDoDraw(TRUE,newlist);
  844.  
  845.          
  846.   for(;;)
  847.     {
  848.       ModalDialog((ModalFilterProcPtr) ListDlgFilter,&itemhit);
  849.       switch(itemhit)
  850.         {
  851.       case Res_DItem_OldList:
  852.       case Res_DItem_NewList:
  853.         {
  854.           fromlist = itemhit==Res_DItem_OldList?oldlist:newlist;
  855.           tolist =   itemhit==Res_DItem_OldList?newlist:oldlist;
  856.           GetPort(&savePort);
  857.           SetPort((*fromlist)->port);
  858.           GetMouse(&mousePt);
  859.           SetPort(savePort);
  860.           
  861.           SetButtonTitle(rearrangedlg,Res_DItem_Move,
  862.                          itemhit==Res_DItem_OldList?"Move >>":"<< Move");
  863.           EnableButton(rearrangedlg,Res_DItem_Move);
  864.           unselectList(tolist);
  865.  
  866.           /* Check for a double-click in the list */
  867.           if(!LClick(mousePt,KeyModifiers,fromlist))
  868.             break;
  869.         }
  870.         
  871.       case Res_DItem_Move:
  872.         {
  873.           /* Move selected items from old to new */
  874.           SetPt(&cell,0,0);
  875.           while(LGetSelect(TRUE,&cell,fromlist))
  876.             {
  877.               short row = LAddRow(1,(*tolist)->dataBounds.bottom+1,tolist);
  878.           char data[256]; short size = 255;
  879.           Cell newcell;
  880.           SetPt(&newcell,0,row);
  881.           LGetCell((Ptr)data,&size,cell,fromlist);
  882.           LSetCell((Ptr)data,size,newcell,tolist);
  883.           cell.v += 1;
  884.  
  885.           if(tolist == newlist)
  886.             {
  887.               EnableButton(rearrangedlg,Res_DItem_Reload);
  888.               ++newfiles;
  889.             }
  890.           else
  891.              --newfiles;
  892.         }
  893.  
  894.           /* Remove from the original list */
  895.           SetPt(&cell,0,0);
  896.           while(LGetSelect(TRUE,&cell,fromlist))
  897.             {
  898.           LDelRow(1,cell.v,fromlist);
  899.         }
  900.  
  901.           /* Reset Buttons */
  902.           DisableButton(rearrangedlg,Res_DItem_Move);
  903.           if(newfiles == 0)
  904.              DisableButton(rearrangedlg,Res_DItem_Reload);
  905.         }
  906.         break;
  907.  
  908.           case Res_DItem_Reload:
  909.         {
  910.           HUnlock((Handle)oldlist);
  911.           HUnlock((Handle)newlist);
  912.           rearrangeprojlist(newlist);
  913.           LDispose(oldlist);
  914.           LDispose(newlist);
  915.               DisposDialog(rearrangedlg);
  916.           HiliteMenu(0);
  917.           updatewindows();
  918.           reloadProjectFiles();
  919.           return;
  920.         }
  921.         
  922.           case CANCEL:
  923.         HUnlock((Handle)oldlist);
  924.         HUnlock((Handle)newlist);
  925.         LDispose(oldlist);
  926.         LDispose(newlist);
  927.             DisposDialog(rearrangedlg);
  928.             return;
  929.         }
  930.     }
  931. }
  932.  
  933.  
  934. unselectList(hlist)
  935. ListHandle hlist;
  936. {
  937.   Cell cell;
  938.   
  939.   SetPt(&cell,0,0);
  940.  
  941.   while(LGetSelect(TRUE,&cell,hlist))
  942.     {
  943.       LSetSelect(FALSE,cell,hlist);
  944.       cell.v+=1;
  945.     }
  946. }
  947.  
  948.  
  949. rearrangeprojlist(new)
  950. ListHandle new;
  951. {
  952.   int file, i, j, max, inorder = TRUE;
  953.   Cell cell;
  954.   int neworder[MAX_PITEMS-1];
  955.   struct ProjStruct Temp[MAX_PITEMS-1];
  956.   char filename[256];
  957.   short size;
  958.   
  959.   SetPt(&cell,0,0);
  960.   
  961.   for(file=0; file < (*new)->dataBounds.bottom; ++file)
  962.     {
  963.       size = 255;
  964.       LGetCell(filename,&size,cell,new);
  965.       filename[size] = '\0';
  966.       neworder[file] = FindPMItem(filename);
  967.       ++cell.v;
  968.    }
  969.   
  970.   for(j = 1; j < projfiles; ++j)
  971.     {
  972.       int found = FALSE;
  973.       
  974.       for(i = 0; i < (*new)->dataBounds.bottom; ++i)
  975.         if(neworder[i] == j)
  976.      {
  977.         found = TRUE;
  978.         break;
  979.       }
  980.  
  981.        if( !found )
  982.          neworder[file++] = j;
  983.      }
  984.  
  985.   for(i = 1; i < projfiles; ++i)
  986.     {
  987.       Temp[i-1] = ProjItems[i];
  988.     }
  989.  
  990.   max = CountMItems(Menu_Project);
  991.   
  992.   while (max > PreludeItem)
  993.     DelMenuItem(Menu_Project,max--);
  994.  
  995.   for(i = 1; i < projfiles; ++i)
  996.     {
  997.       inorder &= i == neworder[i-1];
  998.       ProjItems[i] = Temp[neworder[i-1]-1];
  999.       
  1000.       /* Force a reload for files where the ordering has changed */
  1001.       if(!inorder)
  1002.         PMODTIME(i) = 0;
  1003.     }  
  1004.  
  1005.   for(i = 1; i < projfiles; ++i)
  1006.     insmenuitem(Menu_Project,MNAME(i),PreludeItem+i-1);
  1007. }
  1008.  
  1009.  
  1010. findProjectFile(item)
  1011. {
  1012.   char loadfile[256];
  1013.   int pindex;
  1014.   short vrefnum;
  1015.   long dirID;
  1016.  
  1017.   getitem(Menu_Project,(short)item,loadfile);
  1018.   pindex = FindPMItem(loadfile);
  1019.   vrefnum = PVREFNUM(pindex);
  1020.   dirID = PDIRID(pindex);
  1021.   doopenfile(PNAME(pindex),vrefnum,dirID);
  1022. }
  1023.  
  1024.  
  1025. findPrelude()
  1026. {
  1027.   short path;
  1028.  
  1029.   /* If not already set from resources, set the default prelude name */
  1030.   if(*PreludeName == '\0')
  1031.     PreludeName = DEFAULT_PRELUDE_NAME;
  1032.  
  1033.  
  1034.   /* Look for the prelude in the Gofer folder if we don't know where it is */
  1035.   if (preludevolref == 0 || preludedirID == 0)
  1036.     {
  1037.       extern short gofervol;
  1038.       extern long goferdirID;
  1039.  
  1040.       preludevolref = gofervol;
  1041.       preludedirID = goferdirID;
  1042.     }
  1043.  
  1044.   /* Resolve an aliased prelude */
  1045.   resolvealias(&PreludeName,&preludevolref,&preludedirID,TRUE);
  1046.  
  1047.   /* Check whether the Prelude exists */
  1048.   if(hopen(PreludeName,preludevolref,preludedirID,fsRdPerm,&path) != noErr)
  1049.     {
  1050.       char *prelname = askgetfile(1,texttypelist,"Where is the Gofer Prelude?","Set",Res_Dlg_Where_Prelude,Res_Dlg_SFP_Prelude);
  1051.  
  1052.       if(*prelname != '\0')
  1053.         {
  1054.        PreludeName = safemalloc(strlen(prelname)+1);
  1055.       strcpy(PreludeName,prelname);
  1056.           preludevolref = ReplySpec.vRefNum;
  1057.           preludedirID = ReplySpec.parID;
  1058.     }
  1059.       else
  1060.         {
  1061.           FatalError("Prelude Must Be Specified");
  1062.       return;        /* FatalError just sets quit now */
  1063.     }
  1064.     }
  1065.   else
  1066.     (void) FSClose(path);
  1067. }
  1068.  
  1069.  
  1070. getProjectItem(n)
  1071. int n;
  1072. {
  1073.   short max = CountMItems(Menu_Project)-PreludeItem;
  1074.   char ptitle[256];
  1075.   
  1076.   if(n > max || n < 0)
  1077.     return(-1);
  1078.   else
  1079.     {
  1080.       getitem(Menu_Project,(short)(PreludeItem+n),ptitle);
  1081.       return(FindPMItem(ptitle));
  1082.     }
  1083. }
  1084.  
  1085.  
  1086. Boolean getprojfile(module,file,volnum,dirID)
  1087. int module;
  1088. char *file;
  1089. short *volnum;
  1090. long *dirID;
  1091. {
  1092.   int pindex;
  1093.   if((pindex = getProjectItem(module)) >= 0)
  1094.     {
  1095.       char *afile = PNAME(pindex);
  1096.       *volnum = PVREFNUM(pindex);
  1097.       *dirID = PDIRID(pindex);
  1098.       resolvealias(&afile,volnum,dirID,FALSE);
  1099.       strcpy(file,afile);
  1100.       return(TRUE);
  1101.     }
  1102.   else
  1103.     return(FALSE);
  1104. }
  1105.  
  1106.  
  1107. Boolean getfilefor(defn,line,file,volnum,dirID,dummy)
  1108. char *defn;
  1109. int *line;
  1110. char *file;
  1111. short *volnum, *dummy;
  1112. long *dirID;
  1113. {
  1114.   int module;
  1115.   getName(defn,&module,line);
  1116.   return(getprojfile(module-1,file,volnum,dirID));
  1117. }
  1118.  
  1119.  
  1120. char *scriptname(pindex)
  1121. int pindex;
  1122. {
  1123.   return(PNAME(pindex));
  1124. }
  1125.  
  1126.  
  1127. /* Save and restore directories */
  1128.  
  1129. static short savedvrefnum;
  1130. static long saveddirID; 
  1131.  
  1132. void resetdir()
  1133. {
  1134. #if 0
  1135.   long *curdirstore = (long *)CurDirStore;
  1136.   short *sfsavedisk = (short *)SFSaveDisk;
  1137. #endif
  1138.   HSetVol(NIL,savedvrefnum,saveddirID);
  1139. #if 0
  1140.   *curdirstore = saveddirID;
  1141.   *sfsavedisk = -1 * savedvrefnum;
  1142. #endif
  1143. }
  1144.  
  1145.  
  1146. savedir(vrefnum,dirID,reset)
  1147. short vrefnum;
  1148. long dirID;
  1149. Boolean reset;
  1150. {
  1151.    savedvrefnum = vrefnum;
  1152.    saveddirID = dirID;
  1153. /*   if(reset)*/
  1154.      resetdir();
  1155. }
  1156.  
  1157.  
  1158. changedir(pindex)
  1159. int pindex;
  1160. {
  1161.   long  dirID  = PDIRID(pindex);
  1162.   short volnum = PVREFNUM(pindex);
  1163.   char *file   = PNAME(pindex);
  1164.   
  1165.   resolvealias(&file,&volnum,&dirID,FALSE);
  1166.   HSetVol(NIL,volnum,dirID);
  1167. }
  1168.  
  1169.  
  1170. createTextFile(s)
  1171. char *s;
  1172. {
  1173.   (void) hcreate(s,savedvrefnum,saveddirID,GoferCreatorType,GoferTextType);
  1174. }
  1175.  
  1176.  
  1177. /*
  1178.     Get the modification time for a file.
  1179. */
  1180.  
  1181. unsigned long getmodtime(name,volrefnum,dirID)
  1182. char *name;
  1183. short volrefnum;
  1184. long dirID;
  1185. {
  1186.   HFileParam finfo;
  1187.   char fname[256];
  1188.   
  1189.   resolvealias(&name,&volrefnum,&dirID,FALSE);
  1190.   strcpy(fname,name);
  1191.   
  1192.   finfo.ioCompletion = NIL;
  1193.   finfo.ioNamePtr = c2pstr(fname);
  1194.   finfo.ioVRefNum = volrefnum;
  1195.   finfo.ioFVersNum = 0;
  1196.   finfo.ioFDirIndex = 0;
  1197.   finfo.ioDirID = dirID;
  1198.  
  1199.   PBHGetFInfo((HParmBlkPtr)&finfo,FALSE);
  1200.   
  1201.   return(finfo.ioFlMdDat);
  1202. }
  1203.  
  1204.  
  1205. int haschanged(pindex)
  1206. int pindex;
  1207. {
  1208.   unsigned long modtime = getmodtime(PNAME(pindex),PVREFNUM(pindex),PDIRID(pindex));
  1209.   int changed;
  1210.  
  1211.   if(changed = (modtime > PMODTIME(pindex)))
  1212.     PMODTIME(pindex) = modtime;
  1213.  
  1214.   return(changed);
  1215. }
  1216.  
  1217.  
  1218. int isliterate(pindex)
  1219. {
  1220.   return(IsLiterateFile(PVREFNUM(pindex),PDIRID(pindex),PNAME(pindex)));
  1221. }
  1222.  
  1223. int ishaskmodule(pindex)
  1224. {
  1225.   return(IsHaskNumFile(PVREFNUM(pindex),PDIRID(pindex),PNAME(pindex)));
  1226. }
  1227.  
  1228.  
  1229. Boolean isUserLocked(name,volrefnum,dirID)
  1230. char *name;
  1231. short volrefnum;
  1232. long dirID;
  1233. {
  1234.   HFileParam finfo;
  1235.   char fname[256];
  1236.   
  1237.   resolvealias(&name,&volrefnum,&dirID,FALSE);
  1238.  
  1239.   strcpy(fname,name);
  1240.   
  1241.   finfo.ioCompletion = NIL;
  1242.   finfo.ioNamePtr = c2pstr(fname);
  1243.   finfo.ioVRefNum = volrefnum;
  1244.   finfo.ioFVersNum = 0;
  1245.   finfo.ioFDirIndex = 0;
  1246.   finfo.ioDirID = dirID;
  1247.  
  1248.   PBHGetFInfo((HParmBlkPtr)&finfo,FALSE);
  1249.   
  1250.   return((finfo.ioFlAttrib & 1) != 0);
  1251. }
  1252.  
  1253.  
  1254.  
  1255. long getscriptlen(pindex)
  1256. int pindex;
  1257. {
  1258.   HFileParam finfo;
  1259.   char fname[256];
  1260.   char *name =   PNAME(pindex);
  1261.   short volnum = PVREFNUM(pindex);
  1262.   long  dirID =  PDIRID(pindex);
  1263.   
  1264.   resolvealias(&name,&volnum,&dirID,FALSE);
  1265.  
  1266.   strcpy(fname,name);
  1267.   
  1268.   finfo.ioCompletion = NIL;
  1269.   finfo.ioNamePtr = c2pstr(fname);
  1270.   finfo.ioVRefNum = volnum;
  1271.   finfo.ioFVersNum = 0;
  1272.   finfo.ioFDirIndex = 0;
  1273.   finfo.ioDirID = dirID;
  1274.  
  1275.   PBHGetFInfo((HParmBlkPtr)&finfo,FALSE);
  1276.   
  1277.   return(finfo.ioFlLgLen);
  1278. }
  1279.  
  1280.  
  1281. ListHandle createlist(dlg,item,size,drawframe)
  1282. DialogPtr dlg;
  1283. short item;
  1284. int size;
  1285. Boolean drawframe;
  1286. {
  1287.   ListHandle hlist;
  1288.   Cell cell;
  1289.   Rect listRect, sizeRect;
  1290.  
  1291.   /* Initialise list */
  1292.   GetDlgItemRect(dlg, item, &listRect);
  1293.  
  1294.   SetRect(&sizeRect,0,0,1,size);
  1295.   SetPt(&cell,0,0);
  1296.  
  1297.   listRect.right -= SCROLLBARWIDTH;
  1298.   if(drawframe)
  1299.     FrameDlgList(dlg,listRect);
  1300.  
  1301.   hlist = LNew(&listRect,&sizeRect,cell,NIL,(WindowPtr)dlg,TRUE,FALSE,FALSE,TRUE);
  1302.   HLock((Handle)hlist);
  1303.   LUpdate((*hlist)->port->visRgn,hlist);
  1304.   
  1305.   InsetRect(&(*hlist)->rView,4,4);
  1306.   HUnlock((Handle)hlist);
  1307.  
  1308.   /* Don't draw whilst creating the list */
  1309.   LDoDraw(FALSE,hlist);
  1310.  
  1311.   resetDlgSearch(hlist,FALSE);
  1312.   
  1313.   return(hlist);
  1314. }
  1315.  
  1316.  
  1317. enableSingletons(dlg,hlist,size)
  1318. DialogPtr dlg;
  1319. ListHandle hlist;
  1320. int size;
  1321. {
  1322.   if(size==1)
  1323.     {
  1324.       Cell cell;
  1325.  
  1326.       SetPt(&cell,0,0);
  1327.       LSetSelect(TRUE,cell,hlist);
  1328.  
  1329.       EnableButton(dlg,((DialogPeek)dlg)->aDefItem);
  1330.       if(dlgOtherButton != 0)
  1331.         EnableButton(dlg,dlgOtherButton);
  1332.     }
  1333. }
  1334.  
  1335. Boolean smallerstring(s1,s2)
  1336. char *s1, *s2;
  1337. {
  1338.   for(;*s1!='\0';++s1,++s2)
  1339.     {
  1340.        char c1 = ftolower(*s1), c2 = ftolower(*s2);
  1341.        if(c1 < c2)
  1342.          return(TRUE);
  1343.        else if (c1 > c2)
  1344.          return(FALSE);
  1345.     }
  1346.   return(TRUE);
  1347. }
  1348.  
  1349. static short IndexedModules[MAX_PITEMS];
  1350.  
  1351. short GetModFromIndex(ind)
  1352. short ind;
  1353. {
  1354.   return(IndexedModules[ind]);
  1355. }
  1356.  
  1357. ListHandle SetUpModuleList(dlg,item,drawframe,sort,min)
  1358. DialogPtr dlg;
  1359. short item;
  1360. Boolean drawframe,sort;
  1361. int min;
  1362. {
  1363.   short i, j;
  1364.   ListHandle hlist;
  1365.   Cell cell;
  1366.   char module[256];
  1367.   char *modules[MAX_PITEMS];
  1368.  
  1369.   hlist = createlist(dlg,item,projfiles-min,drawframe);
  1370.  
  1371.   /* Set up the module list. */  
  1372.   for( i=min; i < projfiles; ++i )
  1373.     {
  1374.       getitem(Menu_Project,PreludeItem+i,module);
  1375.  
  1376.       if(sort)
  1377.         {
  1378.           IndexedModules[i-min] = i;
  1379.           modules[i] = safemalloc(strlen(module)+1);
  1380.           strcpy(modules[i],module);
  1381.     }
  1382.       else
  1383.         {
  1384.       SetPt(&cell,0,i-min);
  1385.           LSetCell(module,strlen(module),cell,hlist);
  1386.         }
  1387.     }
  1388.  
  1389.   /* Sort the module list. */  
  1390.   if(sort)
  1391.     {
  1392.       for( i=0; i < projfiles-min; ++i )
  1393.         {
  1394.           for( j=i+1; j < projfiles-min; ++j )
  1395.             {
  1396.               if(!smallerstring(modules[IndexedModules[i]],modules[IndexedModules[j]]))
  1397.             {
  1398.               int temp = IndexedModules[j];
  1399.               IndexedModules[j] = IndexedModules[i];
  1400.               IndexedModules[i] = temp;
  1401.             }
  1402.             }
  1403.     }
  1404.  
  1405.       /* Finally, set the contents of each cell */
  1406.       for( i=0; i < projfiles-min; ++i )
  1407.         {
  1408.           SetPt(&cell,0,i);
  1409.           LSetCell(modules[IndexedModules[i]],strlen(modules[IndexedModules[i]]),cell,hlist);
  1410.           free(modules[IndexedModules[i]]);
  1411.     }
  1412.     }
  1413.  
  1414.  
  1415.   enableSingletons(dlg,hlist,projfiles-min);
  1416.  
  1417.   /* Now draw the list */
  1418.   LDoDraw(TRUE,hlist);
  1419.   
  1420.   HLock((Handle)hlist);
  1421.   LUpdate((*hlist)->port->visRgn,hlist);
  1422.     
  1423.   (*hlist)->selFlags = lOnlyOne;
  1424.   HUnlock((Handle)hlist);
  1425.   
  1426.   resetDlgSearch(hlist,FALSE);
  1427.  
  1428.   return(hlist);
  1429. }
  1430.